package com.cq.hd.order.config;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cq.hd.common.constant.RedisKeyConstant;
import com.cq.hd.common.constant.WxConstant;
import com.cq.hd.common.entity.wx.vo.WeiXinUserList;
import com.cq.hd.common.enums.biz.WxMsgTemplateTypeEnum;
import com.cq.hd.common.utils.RedisUtil;
import com.cq.hd.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class WxPubConfig {

    private final static Integer QR_CODE_EXPIRE_SECOND = 2505600;

    @Value("${wx-pub.appId}")
    public String appId;

    @Value("${wx-pub.appSecret}")
    public String appSecret;

    @Value("${wx-pub.token}")
    public String token;

    @Value("${wx-pub.encodingAesKey}")
    public String encodingAesKey;

    @Value("${wx-pub.refundMsgTemplateId}")
    private String refundMsgTemplateId;

    @Value("${wx-pub.enrollFailMsgTemplateId}")
    private String enrollFailMsgTemplateId;

    @Autowired
    private RedisUtil redisUtil;

    public String getAccessToken() {
        String accessToken = redisUtil.get(String.format(RedisKeyConstant.WX_PUB_TOKEN_KEY, appId));
        if (!StringUtils.isBlank(accessToken)) {
            return accessToken;
        }

        String url = WxConstant.GET_TOKEN_API.replace("APP_ID", appId).replace("SECRET", appSecret);
        JSONObject jsonObject = JSON.parseObject(HttpUtil.get(url));
        accessToken = jsonObject.getString("access_token");
        Integer expiresIn = jsonObject.getInteger("expires_in");

        if (StringUtils.isBlank(accessToken)) {
            log.error("获取微信公众号token异常");
            return "";
        }

        redisUtil.set(String.format(RedisKeyConstant.WX_PUB_TOKEN_KEY, appId), accessToken, expiresIn, TimeUnit.SECONDS);

        return accessToken;
    }

    // 获取临时二维码
    public String getQrCode(String sceneStr) {
        String qrCodeUrl = redisUtil.get(String.format(RedisKeyConstant.WX_PUB_QR_CODE_KEY, sceneStr));
        if (!StringUtils.isBlank(qrCodeUrl)) {
            return qrCodeUrl;
        }

        String accessToken = getAccessToken();
        if (StringUtils.isBlank(accessToken)) {
            log.error("获取临时二维码失败，获取accessToken为空，sceneStr：{}", sceneStr);
            return "";
        }

        Map<String, String> sceneMap = new HashMap<>();
        sceneMap.put("scene_str", sceneStr);

        Map<String, Object> actionInfoMap = new HashMap<>();
        actionInfoMap.put("scene", sceneMap);

        Map<String, Object> paramsMap = new HashMap<>();
        paramsMap.put("action_name", "QR_STR_SCENE");
        paramsMap.put("action_info", actionInfoMap);
        // 该二维码有效时间，以秒为单位。 最大不超过2592000（即30天）   2505600(29天)
        paramsMap.put("expire_seconds", QR_CODE_EXPIRE_SECOND);

        String url = WxConstant.WX_PUB_QRCODE_API.replace("ACCESS_TOKEN", accessToken);
        String result = HttpUtil.post(url, JSON.toJSONString(paramsMap));
        JSONObject jsonObject = JSON.parseObject(result);
        if (jsonObject == null) {
            log.error("获取临时二维码失败，result为空，result：{}", result);
            return "";
        }

        String ticket = jsonObject.getString("ticket");
        Integer expireSeconds = jsonObject.getInteger("expire_seconds");

        if (StringUtils.isBlank(ticket) || expireSeconds == null) {
            log.error("获取临时二维码失败，ticket或expireSeconds为空，result：{}", result);
            return "";
        }

        qrCodeUrl = String.format("https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=%s", ticket);
        redisUtil.set(String.format(RedisKeyConstant.WX_PUB_QR_CODE_KEY, sceneStr), qrCodeUrl, expireSeconds, TimeUnit.SECONDS);

        return qrCodeUrl;
    }

    public Boolean sendTemplateMsg(String openid, WxMsgTemplateTypeEnum wxMsgTemplateTypeEnum, String data) {
        String templateId = "";
        if (WxMsgTemplateTypeEnum.ORDER_EXPIRE_MSG.equals(wxMsgTemplateTypeEnum) || WxMsgTemplateTypeEnum.ORDER_CANCEL_MSG.equals(wxMsgTemplateTypeEnum)) {
            templateId = refundMsgTemplateId;
        } else if (WxMsgTemplateTypeEnum.ENROLL_FAIL_MSG.equals(wxMsgTemplateTypeEnum)) {
            templateId = enrollFailMsgTemplateId;
        }

        if (StringUtils.isBlank(templateId)) {
            log.error("发送微信公众号模板消息失败，templateId为空，openid：{}， templateId：{}", openid, templateId);
            return false;
        }

        String accessToken = getAccessToken();
        if (StringUtils.isBlank(accessToken)) {
            log.error("发送微信公众号模板消息失败，获取accessToken为空，openid：{}， templateId：{}", openid, templateId);
            return false;
        }

        Map<String, Object> paramsMap = new HashMap<>();
        paramsMap.put("touser", openid);
        paramsMap.put("template_id", templateId);
        paramsMap.put("data", JSON.parseObject(data));
        String url = WxConstant.WX_PUB_SEND_TEMPLATE_MSG_API.replace("ACCESS_TOKEN", accessToken);
        // 发送成功 {"errcode":0,"errmsg":"ok","msgid":3344588721505042439}
        // 未关注公众号 {"errcode":43004,"errmsg":"require subscribe rid: 65dd7965-2551590d-5c88c7bc"}
        String result = HttpUtil.post(url, JSON.toJSONString(paramsMap));
        if (StringUtils.isBlank(result)) {
            log.error("发送微信公众号模板消息失败，result为空");
            return false;
        }

        JSONObject jsonObject = JSON.parseObject(result);
        String errcode = jsonObject.getString("errcode");
        if (!"0".equals(errcode)) {
            log.error("发送微信公众号模板消息失败，result:{}", result);
            return false;
        }

        return true;
    }

    public List<String> findWXUserList(List<String> openidList, String nextOpenid) {
        String accessToken = getAccessToken();
        if (StringUtils.isBlank(accessToken)) {
            log.error("获取公众号关注用户失败，获取accessToken为空");
            return null;
        }

        String url = WxConstant.WX_GET_SUBSIDY_USER_INFO_API.replace("ACCESS_TOKEN", accessToken);
        if (StringUtils.isNotBlank(nextOpenid)) {
            url = url + "&next_openid=" + nextOpenid;
        }

        String result = HttpUtil.get(url);
        if (StringUtils.isBlank(result)) {
           return openidList;
        }

        WeiXinUserList weixinUserList = JSON.parseObject(result, WeiXinUserList.class);
        openidList = new ArrayList<>();
        if (weixinUserList.getCount() <= 10000 && weixinUserList.getCount() > 0) {
            openidList.addAll(weixinUserList.getData().getOpenid());
        } else {
            // 如果大于10000的,继续查询
            findWXUserList(openidList, weixinUserList.getNext_openid());
        }

        return openidList;
    }

}
